package dao;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import business.Utilisateur;


public class DaoUtilisateur {
	/* ------------------------------------------------ REQUETES PRECOMPILEES */
	private static CallableStatement statementGetUtilisateur = null;
	private static CallableStatement statementSearchUtilisateur = null;
	private static CallableStatement statementLogin = null;
	private static CallableStatement statementSubscribe = null;
	private static CallableStatement statementTopTenRatio = null;
	private static CallableStatement statementTopTenScore = null;
	private static CallableStatement statementUpdatePointsQuotidien = null;


	/* --------------------------------------------------------- CONSTRUCTEUR */
	static {
		try {
			statementGetUtilisateur = DbConnection.getInstance().prepareCall("{call getUtilisateur(?)}");
			statementSearchUtilisateur = DbConnection.getInstance().prepareCall("{call searchUtilisateur(?, ?)}");
			statementLogin = DbConnection.getInstance().prepareCall("{call login(?, ?)}");
			statementSubscribe = DbConnection.getInstance().prepareCall("{call createUtilisateur(?, ?, ?)}");
			statementTopTenRatio = DbConnection.getInstance().prepareCall("{call getUtilisateurTopTenRatio()}");
			statementTopTenScore = DbConnection.getInstance().prepareCall("{call getUtilisateurTopTenScore()}");
			statementUpdatePointsQuotidien = DbConnection.getInstance().prepareCall("{call updateUtilisateurPointsQuotidien()}");
		}
		catch(SQLException e) {
			e.printStackTrace();
		}
	}


	/* -------------------------------------------------------------- METHODE */
	public static Utilisateur getUtilisateur(int id_utilisateur) {
		Utilisateur utilisateur = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementGetUtilisateur) {
				statementGetUtilisateur.setInt(1, id_utilisateur);
				
				rs = statementGetUtilisateur.executeQuery();
			}
			
			if(rs != null && rs.last()) {
				if(rs.getRow() == 1) {
					double ratio = rs.getInt("nbParisTotal") > 0 ? ((double) rs.getInt("nbParisJustes")) / rs.getInt("nbParisTotal") : 0.0;
					utilisateur = new Utilisateur(
							id_utilisateur,
							rs.getString("mail"),
							rs.getString("pseudo"),
							null, // motDePasse
							rs.getInt("points"),
							rs.getInt("score"),
							rs.getInt("nbParisJustes"),
							rs.getInt("nbParisTotal"),
							ratio);
				}
				else {
					System.err.println("DaoUtilisateur.getUtilisateur(" + id_utilisateur + ") : plusieurs résultats.");
				}
			}
			else {
				System.err.println("DaoUtilisateur.getUtilisateur(" + id_utilisateur + ") : aucun résultat.");
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return utilisateur;
	}


	public static List<Utilisateur> searchUtilisateur(int id_utilisateur, String pseudo) {
		List<Utilisateur> utilisateurs = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementSearchUtilisateur) {
				statementSearchUtilisateur.setInt(1, id_utilisateur);
				statementSearchUtilisateur.setString(2, pseudo);
				
				rs = statementSearchUtilisateur.executeQuery();
			}
			
			if(rs != null) {
				utilisateurs = new ArrayList<Utilisateur>();
				
				while(rs.next()) {
					double ratio = rs.getInt("nbParisTotal") > 0 ? ((double) rs.getInt("nbParisJustes")) / rs.getInt("nbParisTotal") : 0.0;
					utilisateurs.add(new Utilisateur(
							rs.getInt("id_utilisateur"),
							rs.getString("mail"),
							rs.getString("pseudo"),
							null, // motDePasse
							rs.getInt("points"),
							rs.getInt("score"),
							rs.getInt("nbParisJustes"),
							rs.getInt("nbParisTotal"),
							ratio));
				}
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return utilisateurs;
	}


	public static Utilisateur login(String mail, String motDePasse) {
		Utilisateur utilisateur = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementLogin) {
				statementLogin.setString(1, mail);
				statementLogin.setString(2, motDePasse);
				
				rs = statementLogin.executeQuery();
			}
			
			if(rs != null && rs.last()) {
				if(rs.getRow() == 1) {
					double ratio = rs.getInt("nbParisTotal") > 0 ? ((double) rs.getInt("nbParisJustes")) / rs.getInt("nbParisTotal") : 0.0;
					utilisateur = new Utilisateur(
							rs.getInt("id_utilisateur"),
							mail,
							rs.getString("pseudo"),
							motDePasse,
							rs.getInt("points"),
							rs.getInt("score"),
							rs.getInt("nbParisJustes"),
							rs.getInt("nbParisTotal"),
							ratio);
				}
				else {
					System.err.println("DaoUtilisateur.login(" + mail + ", " + motDePasse + ") : plusieurs résultats.");
				}
			}
			else {
				System.err.println("DaoUtilisateur.login(" + mail + ", " + motDePasse + ") : auncun résultat.");
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return utilisateur;
	}


	public static Utilisateur subscribe(String mail, String pseudo, String motDePasse) {
		try {
			synchronized(statementSubscribe) {
				statementSubscribe.setString(1, mail);
				statementSubscribe.setString(2, pseudo);
				statementSubscribe.setString(3, motDePasse);
				
				statementSubscribe.execute();
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return login(mail, motDePasse);
	}


	public static List<Utilisateur> getTopTenRatio() {
		List<Utilisateur> utilisateurs = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementTopTenRatio) {
				rs = statementTopTenRatio.executeQuery();
			}
			
			if(rs != null) {
				utilisateurs = new ArrayList<Utilisateur>();
				
				while(rs.next()) {
					utilisateurs.add(new Utilisateur(
							rs.getInt("id_utilisateur"),
							rs.getString("mail"),
							rs.getString("pseudo"),
							null, // motDePasse
							rs.getInt("points"),
							rs.getInt("score"),
							rs.getInt("nbParisJustes"),
							rs.getInt("nbParisTotal"),
							rs.getDouble("ratio")));
				}
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return utilisateurs;
	}


	public static List<Utilisateur> getTopTenScore() {
		List<Utilisateur> utilisateurs = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementTopTenScore) {
				rs = statementTopTenScore.executeQuery();
			}
			
			if(rs != null) {
				utilisateurs = new ArrayList<Utilisateur>();
				
				while(rs.next()) {
					utilisateurs.add(new Utilisateur(
							rs.getInt("id_utilisateur"),
							rs.getString("mail"),
							rs.getString("pseudo"),
							null, // motDePasse
							rs.getInt("points"),
							rs.getInt("score"),
							rs.getInt("nbParisJustes"),
							rs.getInt("nbParisTotal"),
							rs.getDouble("ratio")));
				}
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return utilisateurs;
	}
	
	public static void updatePointsQuotidien() {
		
		try {
			statementUpdatePointsQuotidien.execute();
		}
		catch(SQLException e) {
			e.printStackTrace();
		}
	}
}
